package hu.ikti.gateway.impl;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.CharBuffer;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @author andraskindler
 * This class is responsible for testing the internet connection. The class variables are
 * <ul>
 * <li>BUF_SIZE - data buffer size</li>
 * <li>connError - connection status</li>
 * <li>toCheck - URL for test</li>
 * <li>timer - variable for setting up a TimerTask</li>
 * <li>period - variable for scheduling</li>
 * </ul>
 *
 */
public class ConnectionChecker {
	
	private static final int BUF_SIZE = 1024;
	private boolean connError;
	private String check = "http://www.google.com/";
	private Timer timer;
	private long period = 1000000;
	public static ConnectionChecker connectionchecker;
	
	/**
	 * This is the base method of the class. It checks for internet connection at the [toCheck URL] through a urlConnection.
	 * It downloads data from the specified URL, the data size is set in the variable BUF_SIZE.
	 * Sets the boolean connError depending on the connection status.
	 */
	private void checkNetworkConnection() {
		
		URL url;
		try {
			url = new URL(getCheck());
			
			URLConnection urlConnection = url.openConnection();
			
			InputStream inputStream = urlConnection.getInputStream();
			Reader reader = new InputStreamReader(inputStream);
			
			StringBuilder contents = new StringBuilder();
			CharBuffer buf = CharBuffer.allocate(BUF_SIZE);
			
			while (true) {
				reader.read(buf);
				if (!buf.hasRemaining())
					break;
				
				contents = contents.append(buf);
			}
			
			inputStream.close();
			connError = false;
		} catch (Exception e) {
			connError = true;
		}
	}
	
	public static ConnectionChecker getInstance() throws Exception {
		
		if (connectionchecker == null) {
			synchronized (ConnectionChecker.class) {
				return connectionchecker = new ConnectionChecker();
			}
		} else
			return connectionchecker;
	}
	
	/**
	 * Sets up a new instance of the ConnectionChecker class. 
	 * 
	 * @param mins Sets the time period (in minutes).
	 * @throws MalformedURLException If the URL address string is badly formed.
	 */
	private ConnectionChecker() throws Exception {
		initTimer();
	}
	
	public void initTimer() {
		
		if (timer != null) {
			timer.cancel();
			timer = null;
		}
		
		if (timer == null) {
			synchronized (ConnectionChecker.class) {
				timer = new Timer();
				TimerTask timertask = new TimerTask() {
					
					@Override
					public void run() {
						CustomLogService.info("Performing scheduled internet connectivity check via " + getCheck() + "...");
						checkNetworkConnection();
						if (connError)
							CustomLogService.error("Error: no internet connection!");
						else
							CustomLogService.info("Internet connection is up.");
					}
				};
				timer.schedule(timertask, 0, getPeriod());
				
			}
		}
	}
	
	/**
	 * Forces a connection check, and returns false if the connection is false.
	 * @return conError;
	 */
	public boolean forceCheck() {
		checkNetworkConnection();
		return connError;
	}
	
	public long getPeriod() {
		return period;
	}
	
	public void setPeriod(Long l) {
		period = l;
		initTimer();
	}
	
	public void setCheck(String check) {
		this.check = check;
	}
	
	public String getCheck() {
		return check;
	}
}
